通过 webrtc和socket 做远程桌面分享
coderzhouyujavascriptwebrtc socket
1. 简单的同文件内两个 peer 服务通信
// 1. 拿到要分享的桌面流
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
// 2. 创建两个端点
/**
const options = {
iceServers: [
{
urls: 'turn:' + 'webrtc-from-chat.glitch.me', // A TURN server
username: 'webrtc',
credential: 'turnserver'
}
]
}
*/
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
// 推流
for (const track of stream.getTracks()) {
pc1.addTrack(track, stream);
}
pc1.onnegotiationneeded = async (e) => {
const offer = await pc1.createOffer();
await pc1.setLocalDescription(offer);
await pc2.setRemoteDescription(offer);
// 创建应答
const answer = await pc2.createAnswer();
await pc2.setLocalDescription(answer);
await pc1.setRemoteDescription(answer);
};
// 设置通信方式
pc1.onicecandidate = (event) => {
if (event.candidate) {
pc2.addIceCandidate(event.candidate);
}
};
pc2.onicecandidate = (event) => {
if (event.candidate) {
pc1.addIceCandidate(event.candidate);
}
};
this.$refs["video"].srcObject = stream;
pc2.addEventListener(
"track",
(e) => {
console.log("得到流", e);
this.$refs["video1"].srcObject = e.streams[0];
},
false
);
2. 通过 socket 分享桌面
使用技术栈 spring-boot + websocket + socketJs 发起端
接受端
<template>
<div class="applicant">
<h2 class="title">人脸识别确认</h2>
<div class="content">
人脸识别确认
<video ref="video" autoplay controls width="200"></video>
</div>
<div class="option">
<button @click="handlerClick">确认</button>
<button>重新选择</button>
</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "FaceConfirm",
data() {
return {
peer: null,
sendCandidate: false,
getOfferState: false,
sendCandidateState: false,
};
},
computed: mapState({}),
mounted() {
setTimeout(() => {
this.$socket.on("closeFaceConfirm", () => {
if (this.peer) {
this.peer.close();
}
debugger;
this.peer = null;
this.$router.push("/");
});
}, 1000);
this.init();
},
methods: {
init() {
this.peer = new RTCPeerConnection();
this.peer.onicecandidate = (event) => {
if (event.candidate && !this.sendCandidate) {
console.log("发送本地凭证", event.candidate);
this.$socket.emit("addIceCandidate2", event.candidate);
this.sendCandidate = true;
}
};
this.$socket.on("receiveOffer", async (offer) => {
if (this.getOfferState) return;
console.log(offer, "我收到offer了");
// 设置offer
await this.peer.setRemoteDescription(offer);
// 创建应答
const answer = await this.peer.createAnswer();
await this.peer.setLocalDescription(answer);
console.log(answer);
// 发送应答给发送端
this.$socket.emit("receiveAnswer", answer);
this.getOfferState = true;
});
this.$socket.on("addIceCandidate", async (candidate) => {
if (this.sendCandidateState) return;
candidate = new RTCIceCandidate(candidate);
await this.peer.addIceCandidate(candidate);
this.sendCandidateState = true;
});
// 等到页面挂载完成 给 video 推流
this.peer.addEventListener(
"track",
(e) => {
console.log("得到流", e);
this.$refs["video"].srcObject = e.streams[0];
},
false
);
},
handlerClick() {
// 提交确定信息给桌面端
// this.$socket.emit()
},
},
};
</script>